﻿using System;

namespace Microsoft.Xna.Framework.Media
{
	/// <summary>
	/// Provides methods and properties to play, pause, resume, and stop songs. MediaPlayer also exposes shuffle, repeat, volume, play position, and visualization capabilities.
	/// </summary>
    public static class MediaPlayer
	{
		#region Fields
		static Song _song;
        static float _volume = 0.5f;
        static bool _isRepeating = true;
		static MediaState state;
		static MediaQueue queue;
		#endregion

		#region Properties
		/// <summary>
		/// Determines whether the game has control of the background music.
		/// </summary>
		public static bool GameHasControl
		{
			get { return true; }
		}

		/// <summary>
		/// Gets or sets the muted setting for the media player.
		/// </summary>
		public static bool IsMuted
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the repeat setting for the media player.
		/// </summary>
		public static bool IsRepeating
		{
			get { return _isRepeating; }
			set
			{
				_isRepeating = value;
				if (_song != null)
				{
					_song.SetRepeating(value);
				}
			}
		}

		/// <summary>
		/// Gets or sets the shuffle setting for the media player.
		/// </summary>
		public static bool IsShuffled
		{
			//! TODO: if possible, implement
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the visualization enabled setting for the media player.
		/// </summary>
		public static bool IsVisualizationEnabled { get; set; }

		/// <summary>
		/// Gets the play position within the currently playing song.
		/// </summary>
		public static TimeSpan PlayPosition
		{
			get { return queue.PlayPosition; }
		}

		/// <summary>
		/// Gets the media playback state, <see cref="T:MediaState"/>.
		/// </summary>
		public static MediaState State
		{
			get { return state; }
			private set
			{
				if (state != value)
				{
					EventHandler<EventArgs> mediaStateChanged = MediaStateChanged;
					if (mediaStateChanged != null)
						mediaStateChanged(null, EventArgs.Empty);

					state = value;
				}
			}
		}

		/// <summary>
		/// Gets or sets the media player volume.
		/// </summary>
        public static float Volume
        {
            get { return _volume; }
            set
            {
                _volume = value;
                if (_song != null)
                {
                    _song.SetVolume(value);
                }
            }
        }
		#endregion

		#region Events
		/// <summary>
		/// Raised when the active song changes due to active playback or due to explicit calls to the MoveNext or MovePrevious methods.
		/// </summary>
		public static event EventHandler<EventArgs> ActiveSongChanged;

		/// <summary>
		/// Raised when the media player play state changes.
		/// </summary>
		public static event EventHandler<EventArgs> MediaStateChanged;
		#endregion

		static MediaPlayer()
		{
			_isRepeating = false;
			queue = new MediaQueue();
		}

		#region Public Methods
		/// <summary>
		/// Retrieves visualization (frequency and sample) data for the currently-playing song. Reference page contains code sample.
		/// </summary>
		/// <param name="visualizationData">Visualization (frequency and sample) data for the currently playing song.</param>
		public static void GetVisualizationData(VisualizationData visualizationData)
		{
			if (visualizationData == null)
			{
				throw new ArgumentNullException("visualizationData", FrameworkResources.NullNotAllowed);
			}

			//! TODO: if possible, implement
		}

		/// <summary>
		/// Moves to the next song in the queue of playing songs.
		/// </summary>
		public static void MoveNext()
		{
			queue.MoveNext();
		}

		/// <summary>
		/// Moves to the previous song in the queue of playing songs.
		/// </summary>
		public static void MovePrevious()
		{
			queue.MovePrevious();
		}

		/// <summary>
		/// Pauses the currently playing song.
		/// </summary>
		public static void Pause()
		{
			if (_song != null)
			{
				_song.Pause();
				State = MediaState.Paused;
			}
		}

		/// <summary>
		/// Plays a Song.
		/// </summary>
		/// <param name="song">Song to play.</param>
		public static void Play(Song song)
        {
            _song = song;
            song.SetRepeating(IsRepeating);
            song.Play();
        }

		/// <summary>
		/// Plays a SongCollection.
		/// </summary>
		/// <param name="songs">SongCollection to play.</param>
		public static void Play(SongCollection songs)
		{
			queue.Play(songs);
		}

		/// <summary>
		/// Plays a SongCollection, starting with the Song at the specified index.
		/// </summary>
		/// <param name="songs">SongCollection to play.</param>
		/// <param name="index">Index of the song in the collection at which playback should begin.</param>
		public static void Play(SongCollection songs, int index)
		{
			queue.Play(songs, index);
		}

		/// <summary>
		/// Resumes a paused song.
		/// </summary>
        public static void Resume()
        {
            if (_song != null)
            {
                _song.Resume();
				State = MediaState.Playing;
            }
        }

		/// <summary>
		/// Stops playing a song.
		/// </summary>
        public static void Stop()
        {
            if (_song != null)
            {
                _song.Stop();
				State = MediaState.Stopped;
            }
		}
		#endregion
	}
}
